package com.javaspeak.designpatterns.go4.behavioural.interpreter;

import java.util.List;

/**
 * The interpreter pattern has a InterpreterContext which the interpreted
 * language can interact with.  This example uses "Object Query Language (oql)"
 * as its interpreted language and the InterpreterContext is used to register
 * Java objects with.   The idea is the once a java object is registered in
 * the InterpreterContext that you can use oql to update the java object with
 * data or to select data from.
 * <p>
 * In the example we are using oql to insert some data into Person and retrieve
 * some data. We print the data retrieved to System.out.
 * <p>
 * The mechanics of the Interpreter pattern in this example work as follows:
 * <p>
 * The interpreter first of all separates the oql into statements. It does this
 * by looking for a ";" separator between the statements. It then executes the
 * statements one by one.
 * <p>
 * Note that the Interpreter uses Expression objects to help it parse data and
 * call the right commands.  In our example we have a InsertExpression and
 * SelectExpression which both extends the abstract class AbstractExpression.
 * <p>
 * If a oql statement starts with "insert" the interpreter knows to use the
 * InsertExpression to perform the parsing and call setFieldValue(..) method
 * on the InterpreterContext.
 * <p>
 * If however the oql statement starts with "select" the interpreter knows to
 * use the SelectStatement to perform the parsing and call getFieldValue(..)
 * method on the InterpreterContext and add the selected values to the
 * valuesToReturn list.
 *
 * @author John Dickerson
 */
public class InterpreterApplication {

    /**
     * Runs example
     *
     * @throws Exception
     */
    public void runExample() throws Exception {

        InterpreterContext interpreterContext = new InterpreterContext();

        // register an object with the interpreter which we wish to insert data
        // into or select data from
        interpreterContext.registerObject( new Person() );

        Interpreter interpreter = new Interpreter( interpreterContext );

        // Build up an insert statement and select statement. Seperate the
        // statements by ";"
        StringBuilder sb = new StringBuilder();
        sb.append( "insert into " ).append( Person.class.getName() );
        sb.append( " firstName=John lastName=Dickerson height=180;" );
        sb.append( "select height, firstName, lastName from " );
        sb.append( Person.class.getName() ).append( ";" );

        // Object Query Language
        String oql = sb.toString();

        // Call the interpreter to execute the oql and return values.
        List<Value> values = interpreter.interpret( oql );

        // Print the values retrieved to System.Out
        for ( Value value : values ){

            System.out.print( value + " " );
        }
    }


    public static void main(String[] args) throws Exception {

        InterpreterApplication application = new InterpreterApplication();
        application.runExample();
    }
}
